package base.thread_demo.demo13;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * 同步模式之保护性暂停改进版：t1线程等待给定时间就不再等待。防止t2线程一直没返回，t1一直等待下去
 *
 */
public class GuardedSuspension2 {
    private static final Logger log = LoggerFactory.getLogger(GuardedSuspension2.class);
    private static Guarded guarded = new Guarded();

    public static void main(String[] args) {
        new Thread(()->{
            try {
                List<String> content = guarded.getContent(5000);
                log.info("{}得到下载的网页代码行数为：{}",Thread.currentThread().getName(), content.size());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t1").start();

        new Thread(()->{
            try {
                List<String> content = Downloader.downloader();
                guarded.setContent(content);
            } catch (Exception e) {
                e.printStackTrace();
            }
        },"t2").start();
    }




    static class Guarded {
        //下载的内容,t1,t2共享变量
        private List<String> content;


        public synchronized void setContent(List<String> content){
            this.content = content;
            this.notifyAll();// 唤醒t1,可以输出了
        }

        /**
         * 该方法内部逻辑跟Thread的join()方法类似
         * @param timeout
         * @return
         * @throws InterruptedException
         */
        public synchronized List<String> getContent(long timeout) throws InterruptedException {
            // 执行获取数据开始时间
            long begin = System.currentTimeMillis();
            // 已等待时间
            long passed = 0;

            while(content == null){
                // 剩余等待时间
                long wait = timeout - passed;
                if(wait <= 0) {
                    break;
                }
                this.wait(wait);// 因存在虚假唤醒可能，wait时间不能直接是timeout,set()方法不保证response不为null而虚假唤醒
                passed = System.currentTimeMillis() - begin;
            }
            return content;
        }
    }
}
